﻿namespace ExcelExportCS;

public static class Template
{
    /// <summary>
    /// 文件头
    /// </summary>
    public const string FileHeader = """
                                     using System.Text.Json;

                                     namespace {0}.ExcelDefine;

                                     """;

    /// <summary>
    /// 成员变量模板
    /// </summary>
    public const string MemberNumberFmt = "\tpublic {0} {1} {{ get; private set; }} // {2}";

    public const string MemberStringFmt = "\tpublic {0} {1} {{ get; private set; }} = string.Empty; // {2}";
    public const string MemberArrayFmt = "\tpublic {0} {1} {{ get; private set; }} = []; // {2}";
    public const string MemberObjectNewFmt = "\tpublic {0} {1} {{ get; private set; }} = new(); // {2}";

    /// <summary>
    /// 成员变量读取模板
    /// </summary>
    public const string MemberReadFmt = "\t\t{0} = (data[{2}] as JsonElement? ?? default).Deserialize<{1}>()!;";

    /// <summary>
    /// 类模板
    /// </summary>
    public const string ClassTemplateFmt = """
                                           // {0} => {1}
                                           public class {2}Class : IInitClass
                                           {{
                                           {3}
                                           
                                               public void Init(List<object> data)
                                               {{
                                           {4}
                                               }}
                                           }};

                                           """;

    /// <summary>
    /// 类模板
    /// </summary>
    public const string ClassTemplateMapFmt = """
                                              // {0} => {1}
                                              public class {2}Class : IExcelClass
                                              {{
                                              {3}
                                              
                                                  public void Init(List<object> data)
                                                  {{
                                              {4}
                                                  }}
                                              }};

                                              """;

    /// <summary>
    /// 加载器成员变量模板
    /// </summary>
    public const string LoaderMemberFmt = "\tpublic {0}Class {0} {{ get; }} = new();";

    public const string LoaderMemberMapFmt = "\tpublic ExcelPrimaryClass<{0}Class> {0}Map {{ get; }} = new();";
    public const string LoaderMemberGroupMapFmt = "\tpublic ExcelGroupClass<{0}Class> {0}Map {{ get; }} = new();";

    /// <summary>
    /// 加载器参数读取模板
    /// </summary>
    public const string LoaderParamReadFmt = """
                                                         if (!dictData.TryGetValue("{1}", out var {1}Obj))
                                                         {{
                                                             err = "{2}Loader json deserialize {0} error";
                                                             return false;
                                                         }}
                                                         
                                                         if (!ExcelParamClass<{0}Class>.Init({0}, {1}Obj, out err) && err != null)
                                                         {{
                                                             err = "{2}Loader MailConfigRef Init error";
                                                             return false;
                                                         }}
                                                         
                                             """;

    /// <summary>
    /// 加载器类映射读取模板
    /// </summary>
    public const string LoaderClassMapReadFmt = """
                                                            if (!dictData.TryGetValue("{1}", out var {1}Obj))
                                                            {{
                                                                err = "{2}Loader json deserialize {0} error";
                                                                return false;
                                                            }}
                                                            
                                                            if (!{0}Map.Init({1}Obj, out err))
                                                            {{
                                                                err = "{2}Loader init {0}Map error";
                                                                return false;
                                                            }}

                                                """;

    /// <summary>
    /// 加载器模板
    /// </summary>
    public const string LoaderTemplateFmt = """
                                            public class {0}Loader
                                            {{
                                            {1}
                                                
                                                public bool Load(string filePath, out string? err)
                                                {{
                                                    err = null;
                                                    try
                                                    {{
                                                        var dictData = JsonSerializer.Deserialize<Dictionary<string, object>>(File.ReadAllText(filePath));
                                                        if (dictData == null)
                                                        {{
                                                            err = "{0}Loader json deserialize error";
                                                            return false;
                                                        }}
                                                        
                                            {2}
                                                        return true;
                                                    }}
                                                    catch (Exception ex)
                                                    {{
                                                        err = ex.Message;
                                                        return false;
                                                    }}
                                                }}
                                            }}
                                            """;

    /// <summary>
    /// 固定导出的文件
    /// </summary>
    public const string ExcelClassFileName = "Interface.cs";

    public const string ExcelClassInterfaceFmt = """
                                                 using System.Text.Json;

                                                 namespace {0}.ExcelDefine;
                                                 
                                                 public interface IInitClass
                                                 {{
                                                     public void Init(List<object> data);
                                                 }}

                                                 public interface IExcelClass: IInitClass
                                                 {{
                                                     int Id {{ get; }}
                                                 }}

                                                 public class ExcelGroupClass<T> where T : IExcelClass, new()
                                                 {{
                                                     private Dictionary<int, List<T>> DataMap {{ get; }} = new();
                                                 
                                                     public bool Init(object obj, out string? err)
                                                     {{
                                                         err = null;
                                                 
                                                         var listData = obj as JsonElement?;
                                                         foreach (var element in listData?.EnumerateArray()!)
                                                         {{
                                                             try
                                                             {{
                                                                 var item = new T();
                                                                 item.Init(JsonSerializer.Deserialize<List<object>>(element.Deserialize<string>()!)!);
                                                                 if (!DataMap.TryGetValue(item.Id, out var groupList))
                                                                 {{
                                                                     groupList = new List<T>();
                                                                     DataMap[item.Id] = groupList;
                                                                 }}
                                                 
                                                                 groupList.Add(item);
                                                             }}
                                                             catch (Exception ex)
                                                             {{
                                                                 err = ex.Message;
                                                                 return false;
                                                             }}
                                                         }}
                                                 
                                                         return true;
                                                     }}
                                                 
                                                     public List<T>? FindById(int id)
                                                     {{
                                                         return DataMap.GetValueOrDefault(id);
                                                     }}
                                                 }}

                                                 public class ExcelPrimaryClass<T> where T : IExcelClass, new()
                                                 {{
                                                     private Dictionary<int, T> DataMap {{ get; }} = new();
                                                 
                                                     public bool Init(object obj, out string? err)
                                                     {{
                                                         err = null;
                                                 
                                                         var listData = obj as JsonElement?;
                                                         foreach (var element in listData?.EnumerateArray()!)
                                                         {{
                                                             try
                                                             {{
                                                                 var item = new T();
                                                                 item.Init(JsonSerializer.Deserialize<List<object>>(element.Deserialize<string>()!)!);
                                                                 DataMap[item.Id] = item;
                                                             }}
                                                             catch (Exception ex)
                                                             {{
                                                                 err = ex.Message;
                                                                 return false;
                                                             }}
                                                         }}
                                                 
                                                         return true;
                                                     }}
                                                 
                                                     public T? FindById(int id)
                                                     {{
                                                         return DataMap.GetValueOrDefault(id);
                                                     }}
                                                 }}
                                                 
                                                 public abstract class ExcelParamClass<T> where T : IInitClass, new()
                                                 {{
                                                     public static bool Init(T t, object obj, out string? err)
                                                     {{
                                                         err = null;
                                                 
                                                         var listData = obj as JsonElement?;
                                                         foreach (var element in listData?.EnumerateArray()!)
                                                         {{
                                                             try
                                                             {{
                                                                 t.Init(JsonSerializer.Deserialize<List<object>>(element.Deserialize<string>()!)!);
                                                             }}
                                                             catch (Exception ex)
                                                             {{
                                                                 err = ex.Message;
                                                                 return false;
                                                             }}
                                                         }}
                                                 
                                                         return true;
                                                     }}
                                                 }}
                                                 """;


    /// <summary>
    /// 读表管理器的成员变量
    /// </summary>
    public const string ConfigMgrMemberFmt = "    public {0}Loader {0} {{ get; private set; }} = new();";

    /// <summary>
    /// 读表管理器的加载方法
    /// </summary>
    public const string ConfigMgrReadFmt = """
                                                   if (!{1}.Load(Path.Combine(jsonPath, "{0}.json"), out err) && err != null)
                                                   {{
                                                       return false;
                                                   }}
                                                   
                                           """;

    /// <summary>
    /// 配置管理类
    /// </summary>
    public const string ConfigMgrClassFmt = """
                                             namespace {0}.ExcelDefine;

                                             public class ConfigMgr
                                             {{
                                                 private static ConfigMgr? _instance;
                                             
                                                 public static ConfigMgr Instance
                                                 {{
                                                     get {{ return _instance ??= new ConfigMgr(); }}
                                                 }}
                                             
                                             {1}
                                             
                                                 public bool Load(string jsonPath, out string? err)
                                                 {{
                                                     err = null;
                                                     
                                             {2}
                                                     return true;
                                                 }}
                                             }}
                                             """;
}